package com.aliyun.messagemgt.entity;

import org.apache.commons.collections.CollectionUtils;
import org.junit.Test;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: li.wy
 * @create: 2020-11-30
 **/
public class EntityVoTestUtils {
    //实体化数据
    private static final Map<String, Object> STATIC_MAP = new HashMap<String, Object>();

    //忽略的函数方法method
    private static final String NO_NOTICE = "getClass,notify,notifyAll,wait,equals,hashCode,clone";

//    private static final List<Class> CLASS_LIST = new ArrayList<Class>();

    static {
        ArrayList<Object> list = new ArrayList<>();
        list.add(new Date());
        byte[] bytes = {};

        STATIC_MAP.put("java.lang.Byte", (byte)1);
        STATIC_MAP.put("java.lang.Short", (short)1);
        STATIC_MAP.put("java.lang.Integer", 1);
        STATIC_MAP.put("java.lang.Long", 1L);
        STATIC_MAP.put("java.lang.Double", 1.1);
        STATIC_MAP.put("java.lang.Boolean", true);
        STATIC_MAP.put("java.lang.String", "2020-12-01 00:00:00");
        STATIC_MAP.put("java.lang.String[]", new String[]{});

        STATIC_MAP.put("char", '1');
        STATIC_MAP.put("int", 1);
        STATIC_MAP.put("long", 1);
        STATIC_MAP.put("boolean", true);

        STATIC_MAP.put("byte[]", bytes);

        STATIC_MAP.put("java.util.Date", new Date());
        STATIC_MAP.put("java.util.Map", new HashMap());
        STATIC_MAP.put("java.util.List", list);
        STATIC_MAP.put("java.sql.Timestamp", new Timestamp(new Date().getTime()));
        STATIC_MAP.put("java.math.BigDecimal", new BigDecimal("0"));
        STATIC_MAP.put("java.lang.Object", new Object());
//        CLASS_LIST.add(.class);
//        CLASS_LIST.add(.class);
    }


    /**
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    @Test
    public void justRun() throws IllegalAccessException, InvocationTargetException, InstantiationException {
        List<Class> CLASS_LIST = getClasses();
        for (Class temp : CLASS_LIST) {
            Object tempInstance = new Object();
            //执行构造函数
            Constructor[] constructors = temp.getConstructors();
            for (Constructor constructor : constructors) {
                final Class<?>[] parameterTypes = constructor.getParameterTypes();
                if (parameterTypes.length == 0) {
                    tempInstance = constructor.newInstance();
                } else {
                    Object[] objects = new Object[parameterTypes.length];
                    for (int i = 0; i < parameterTypes.length; i++) {
                        objects[i] = STATIC_MAP.get(parameterTypes[i].getName());
                    }
                    tempInstance = constructor.newInstance(objects);
                }
            }

            //执行函数方法
            Method[] methods = temp.getMethods();
            methodInvoke(methods, tempInstance);
        }
    }

    private void methodInvoke(Method[] methods, Object tempInstance) throws InvocationTargetException, IllegalAccessException {
        for (final Method method : methods) {
            try {
                if (NO_NOTICE.contains(method.getName())) {
                    break;
                }
                final Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length != 0) {
                    Object[] objects = new Object[parameterTypes.length];
                    for (int i = 0; i < parameterTypes.length; i++) {
                        if(!STATIC_MAP.containsKey(parameterTypes[i].getTypeName())){
                            System.out.println(method.getName() + "=========>" + parameterTypes[i].getTypeName());
                        }else{
                            objects[i] = STATIC_MAP.get(parameterTypes[i].getTypeName());
                        }
                    }

                    method.invoke(tempInstance, objects);
                } else {
                    Object invoke = method.invoke(tempInstance);

                    if(method.getName().equals("createCriteria")){
                        Class<?> subClass = invoke.getClass();
                        Method[] subMethods = subClass.getMethods();
                        methodInvoke(subMethods, invoke);
                    }
                }
            }catch (Exception e){
            }
        }
    }


    public List<Class> getClasses() {
        String path = "src/main/java/com/aliyun/mgt/account/infrastructure/entities";
        List<String> models = new ArrayList<>();
        List<Class> classes = new ArrayList<>();
        readFiles(path, models);
        if(CollectionUtils.isNotEmpty(models)){
            models.forEach(e -> {
                try {
                    Class<?> forName = Class.forName(e);
                    classes.add(forName);
                } catch (ClassNotFoundException classNotFoundException) {
                    classNotFoundException.printStackTrace();
                }
            });
        }
        return classes;
    }

    /**
     * 递归读取文件夹下的文件
     * @param path
     */
    public void readFiles(String path, List<String> models) {
        File file = new File(path);
        // 如果是文件夹，则需要递归处理
        if(file.isDirectory()) {
            File[] files = file.listFiles();
            for (File currentFile : files) {
                if(currentFile.isDirectory()) {
                    readFiles(currentFile.getPath(), models);
                } else  {
                    String fileName = currentFile.getPath().substring(0, currentFile.getPath().indexOf("."));
                    fileName = fileName.substring(indexOfStr(fileName, "\\\\", 3) + 1).replaceAll("\\\\", ".");

                    models.add(fileName);
                }
            }
        } else {
            String fileName = file.getPath().substring(0, file.getPath().indexOf("."));
            fileName = fileName.substring(indexOfStr(fileName, "\\\\", 3) + 1).replaceAll("\\\\", ".");

            models.add(fileName);
        }

    }

    public static Integer indexOfStr(String str,String findStr, int index){
        Pattern pattern = Pattern.compile(findStr);
        Matcher findMatcher = pattern.matcher(str);
        int number = 0;
        while(findMatcher.find()) {
            number++;
            if(number == index){
                break;
            }
        }
        try {
            return findMatcher.start();
        } catch (Exception e) {
            return null;
        }
    }

}